
<p>FreeWPC uses the <b>netpbm</b> graphics toolkit to work with images.
This article describes an overview of how images are handled.</p>

<h2>WPC Hardware Overview</h2>

<p>The dot matrix display on a WPC pinball is a 128x32 matrix of pixels.
Each pixel can only be on or off; it is monochrome only.  The perception
of different shades of color is performed by trickery: if you rapidly
change the image being displayed, pixels which are on more often will
appear to be brighter.</p>

<p>The current FreeWPC program only supports 4-color images.  That is,
each pixel position can take 1 of four values: 00, 01, 10, or 11.  To
simulate this, the controller alternates between 2 different images,
showing one 1/3 of the time and another 2/3 of the time.  When 
corresponding pixels are both on or both off, they appear totally off
or totally bright.  Pixels on in the 1/3 image but off in the 2/3 image
will appear dark.  Pixels on in the 2/3 image but off in the 1/3 image
will appear slightly less than bright.  This allows for 3 different shades
plus 1 completely dark color.</p>

<p>FreeWPC could be made to support more colors, by requiring more "planes"
of the image to be defined.  An 8-color (7 shades plus off) image would
require 3 planes.  It would also require a more complicated switching
algorithm: one plane at 1/7, another at 2/7, and the last at 4/7 of the
time.</p>

<p>Regardless of the color scheme, the raw images or planes of images are
all just 128x32 arrays of pixels.  In the future, these could be
compressed in order to conserve ROM space; for now, ROM space is not
an issue so this hasn't been implemented.</p>

<h2>NetPBM Overview</h2>

<p>NetPBM defines a number of image formats.  The primary format for
developing new images is the <b>PGM</b> file, which is a variable-sized
grayscale file in which each pixel can have 1 of 256 different color
values (shades of gray).  The PPM should not be used, since it is
intended for true color images.  The PAM format provides support for
alpha transparency, but FreeWPC doesn't have the hooks to deal with that.</p>

<p>A PGM file declares its width and height in pixels, and then defines
the grayscale value at each of the pixel positions.  It is a very
simple format.  It can be edited by hand or by scripts, plus all of the
major graphics programs (Photoshop and GIMP) can work with it, so images
in other formats can be scaled down to PGM easily.</p>

<p>PGM files need not be 128x32 in size; NetPBM provides tools for
working with PGM files, such as overlaying images, cutting/pasting,
scaling, inverting, etc.  If there are common elements to multiple
frames, they should be in their own PGM files, and NetPBM can be used
to construct the 128x32 frames from the input "layers".</p>

<h2>Frame Construction</h2>

<p>Eventually, though, you will need to produce a 128x32 PGM file for each
full frame to be displayed on the DMD.  However, the PGM file itself is
not suitable for inclusion into the game ROM.  PGMs must be translated
into another format, called <b>XBM</b>, which is suitable.</p>

<p>XBM is used for two purposes.  First, the file is actually just plain old
C code, that can be compiled and linked right into the program like any
other source file.  XBMs declare a static array of char data representing
the image.  </p>

<p>Second, XBM is a 1 color format, which is what our dot matrix display wants.
The conversion from PGM to XBM is a lossy one, but there are multiple ways
to do it.  If we want a 4-color image, that will require two XBM frames.
A monochrome image can be generated as a single XBM frame.</p>

<p>FreeWPC provides a script, <b>tools/pgmtoxbm2</b>, that generates 4-color
images from an arbitrary PGM file.  It does this by normalizing the 256
grayscale values of the input image into 4 output values, and then
distributing each of the 2 data bits into 2 different XBM files.
(Note that more realistic images could be generated by <i>dithering</i>,
using the <b>pamditherbw</b> tool, but I haven't tried that yet.)</p>

<h2>NetPBM Utilities</h2>

<p>Here is a list of useful netpbm programs for transforming PGM files:</p>

<ul>
<li>pgmmake - make a blank file of a given size
<li>pgmnoise - make a new file with white noise
<li>pamscale - enlarge a file the dumb and simple way
<li>pamditherbw - use dithering to reduce the number of colors
<li>pnmcat - concatenate multiple images
<li>pnmcomp - overlay image
<li>pamcut - cut a region from an image
<li>pamdepth - scale all pixels to a new maxval
<li>pamflip - flip an image
<li>pamstretch - enlarge by interpolation
<li>pnminvert - invert an image
<li>pnmpaste - paste rectangular region into an image
<li>pnmrotate - rotate an image
<li>pbmclean - remove lone pixels from a 1-bit image
</ul>

<h2>Font Files</h2>

<p>A FreeWPC font file is just a collection of XBM image files, where
each image represents a single character in the font.  NetPBM provides
the tool <b>pbmtotextps</b> for generating images from X fonts.
You can run the <b>xfontsel</b> tool to preview various X fonts and
determine the font name that corresponds to the desired family, point size,
weight, etc.  Then, use NetPBM to generate the XBM for all of the
characters that you want to represent in that font.</p>

<p>The <b>.fon</b> files contain ancillary data in addition to the
font glyphs themselves.  For example, even in a single font, the size of
all characters is not alike; some are wider or taller than others.
So size information is preserved.  Also, not all glyphs need be
represented in a font, for example, if the font is only used for displaying
numbers, then the alphabetics can be omitted to keep the font file smaller.</p>

<p>The <b>fontgen</b> script provided by FreeWPC does this semi-
automatically.  It is possible to run this on Cygwin, but the emulation
makes it painfully slow to do so.  FreeWPC comes with font files
out-of-the-box to use, so not all developers are not required to have these
tools unless custom font/image editing is desired.</p>

